﻿/* Q1 is a networking library that I've started when I was on vacations. It's under development too. */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Security.Cryptography;

namespace Q1
{
    /// <summary>
    /// Holds the common classes of the Q1 technology.
    /// </summary>
    public class RRR
    {
        public class BasicQ1BinaryFormationDePatchException : Exception
        {
            public BasicQ1BinaryFormationDePatchException() : base("Error during the DePatch() operation.") { }
        }

        public class BasicQ1BinaryFormationPatchException : Exception
        {
            public BasicQ1BinaryFormationPatchException() : base("Error during the Patch() operation.") { }
        }

        /// <summary>
        /// Represents a Basic Binary Formatter.
        /// </summary>
        public class BasicQ1BinaryFormation
        {
            private RSAOAEPKeyExchangeFormatter fmt = new RSAOAEPKeyExchangeFormatter();

            private byte[] key;
            private int size;

            /// <summary>
            /// Initializes a new instace of a BasicQ1BinaryFormation class.
            /// </summary>
            public BasicQ1BinaryFormation()
            {
                fmt.SetKey(new RSACryptoServiceProvider());
                key = fmt.CreateKeyExchange(BitConverter.GetBytes(2012));
                size = key.Length;
            }

            /// <summary>
            /// Formats an array of bytes using the Q1BasicFormation method.
            /// </summary>
            /// <param name="orig">The array to format.</param>
            /// <returns></returns>
            public byte[] Patch(byte[] orig)
            {
                try
                {
                    int pkey = 0;
                    int tempKey = 0;
                    for (int i = 0; i < size; i++)
                    {
                        tempKey = key[i];
                        pkey += tempKey * key[i];
                    }

                    byte[] patch = new byte[orig.Length];

                    for (int i = 0; i < orig.Length; i++)
                    {
                        patch[i] = (byte)(orig[i] + pkey);
                    }

                    MemoryStream memsr = new MemoryStream();
                    BinaryWriter writer = new BinaryWriter(memsr);
                    writer.Write(size);
                    writer.Write(key);
                    writer.Write(patch);
                    byte[] lpPatch = memsr.ToArray();
                    writer.Close();

                    return lpPatch;
                }
                catch (Exception)
                {
                    throw new BasicQ1BinaryFormationPatchException();
                }
            }

            /// <summary>
            /// Deformats an array of bytes using the Q1BasicFormation method.
            /// </summary>
            /// <param name="patch">The array to deformat.</param>
            /// <returns></returns>
            public byte[] DePatch(byte[] patch)
            {
                try
                {
                    int pkey = 0;
                    int tempKey = 0;

                    MemoryStream memsr = new MemoryStream(patch);
                    BinaryReader reader = new BinaryReader(memsr);

                    int s = reader.ReadInt32();
                    byte[] lpKey = reader.ReadBytes(s);

                    byte[] lpPatch = reader.ReadBytes((int)memsr.Length - (4 + s));

                    for (int i = 0; i < size; i++)
                    {
                        tempKey = lpKey[i];
                        pkey += tempKey * lpKey[i];
                    }

                    byte[] orig = new byte[lpPatch.Length];

                    for (int i = 0; i < orig.Length; i++)
                    {
                        orig[i] = (byte)(lpPatch[i] - pkey);
                    }
                    return orig;
                }
                catch (Exception)
                {
                    throw new BasicQ1BinaryFormationDePatchException();
                }
            }
        }
    }
}
